"""--------------------------------------------------------------------------------------------------
Filename:   config.py
Author:     Ben Han (uha10@uclive.ac.nz)
Date:       17 May 2010
Description:
    Defines classes to store and edit configuration variables for the biofeedback application.
    
    There are three main state variable container objects used by the application:
        ConfigData - stores the configuration options for new sessions
        AppState - stores state information related to the application
        SessionState - created each time a new session is started and stores
            dynamic variables e.g. mode, trial index, etc
    
    There is also a separate class which provides the GUI layer for the configuration window: 
        ConfigPanel - this is the GUI layer for the user to modify configuration variables 
--------------------------------------------------------------------------------------------------"""
 
import wx, sys
from decimal import Decimal

#===============================================================================
# CLASS: ConfigData
#    A storage class used to store the settings for a session
#===============================================================================
class ConfigData:
    # Stores the configuration information for the application.
    # Values marked with a prefix "_" are initial values for configurable controls
    
    # STATIC VARIABLES ----------
    _trials_per_session = 100
    _trials_per_block = 20
    _trial_len = 30
    _break_len = 100
    
    # delay protocol options --------------------------------------------
    _use_fading = False         # Turns the automatic fading schedule on or off
    # First number is the number of trials with plots on, second number is trials with plot off
    # each pair represents one block of trials
    fading_schedule = [(1,1),(1,2),(2,1),(2,2),(3,1)]
    
    # Delay protocol options ---------------------------------------------
    _use_delay = False          # Set state of delayed feedback feature
    _delay_len = 5 
    
    # MISCELLANEOUS
    _port = 'COM3'

    # PLOT
    default_grid = False        # initial setting for plot options
    default_plot = True         # initial setting for plot options
    default_time = False        # initial setting for plot options
    default_ampl = False        # initial setting for plot options
    _sample_rate = 10
    y_margin = 20               # Proportional margin (in %) to add to Y-axis max for auto-scaling
    _y_axis_max_init = 200      # initial Y axis range during calibration
    _y_axis_max = 200           # Y axis range
    _plot_back_color = (1.0, 1.0, 1.0, 1.0)
    _plot_line_color = (0.0, 0.0, 1.0, 1.0)
    _plot_line_width = 3        # The width of the plot line
    _target_line_width = 3
    _target_color = (0.4, 0.8, 0.0, 1.0)
    _target_aspect_ratio = False    # flag to indicate whether to draw a target that has equal side lengths in the plot

    # STRENGTH TRAINING
    str_init_value = 100            # % of baseline value from calibration
    _str_increment = 10             # % proportion in which to change the size of the target
    _str_miss_tol = 3               # number of misses before target is increased
    _str_hit_tol = 3                # number of hits before target is decreased
    _str_running_count = False      # Flag to indicate whether to use a running count
    _str_hit_incr = 1               # Amount to increment running count when hit
    _str_miss_incr = 1              # Amount to decrement running count when missed
    _y_margin_strength = 2.2        # Multiplied by calibration mean to get y axis max

    # SKILL TRAINING
    init_size_x = 10            # absolute value in seconds
    init_size_y = 50            # % of baseline value from calibration
    target_test_margin = 0.5    # width margin for testing target hit (in seconds)
    _increment = 10             # % proportion in which to change the size of the target
    _miss_tol = 3               # number of misses before target is increased
    _hit_tol = 3                # number of hits before target is decreased
    _running_count = False      # Flag to indicate whether to use a running count
    _hit_incr = 1               # Amount to increment running count when hit
    _miss_incr = 1              # Amount to decrement running count when missed
    _lower_limit = 0.3          # Lower range limit for target placement
    _upper_limit = 0.9          # Upper range limit for target placement
    _x_margin = 2               # Time axis range limits for target placement
    _y_margin_skill = 1.2       # Multiplied by calibration mean to get y axis max
    
    def __init__(self):
        pass

#===============================================================================
# CLASS: AppState
#    Used to store main application state information
#===============================================================================
class AppState:
    # Stores dynamic application state information
    def __init__(self):
        self.patient = None             # Place holder for reference to current patient
        self.patient_changed = False      # Flags whether the display values have been saved to file
        self.session = None             # Place holder for reference to current session
        self.session_disp = None        # Place holder for reference to displayed session in mainframe
        self.session_changed = False   # Flags whether the current session displayed in the session pane has been saved to the patient
        self.ctrl_frame = False         # Flag to indicate that the control panel is visible
        self.plot_frame = False         # Flag to indicate that the plot frame is visible


#===============================================================================
# CLASS: SessionState
#    Used to store session state information
#===============================================================================
class SessionState:
    # Stores dynamic session state information
    def __init__(self):
        self.type = ''               # training type
        self.y_index = Decimal(0)    # index for EMG data array
        self.str_target = 0          # value of the current strength target
        self.baseline = 0            # Starting target amplitude after calibration
        self.peak = (0, 0)           # Peak for the last trial (that was tested against the target)
        self.target_hits = 0         # Number of times the current target has been hit consecutively
        self.target_misses = 0       # Number of times the current target has been missed consecutively
        self.count = 0               # Running count of the hits/misses
        self.history = []            # History of hits and misses
        
        self.min_range = [0, 0]
        self.max_range = [0, 0]
        self.min_size = [0, 0]
        self.max_size = [0, 0]
    
        self.alive = False           # Flag to indicate whether to record data from serial port
        self.ymax_auto = False       # Flag to indicate that y-axis auto-scaling is on 
    
        self.result = False          # Flag to say if target has been hit
        self.target_on = False       # Flag to indicate that a target has been drawn
        self.timeline = False        # Flag to indicate that a time line has been drawn
        self.amplline = False        # Flag to indicate that a amplitude line has been drawn
    
        self.serial_open = False     # Flag to indicate when the serial port is open
        self.saved = False           # Flag to indicate that the current session has been saved to the patient
    
        self.calib_index = 0
        self.trial_index = 0
        self.block_index = 0
        self.delay_mark = 100
        self.fading_phase = False   # indicates if fading is being used or not (True = plot not visible)
        self.plots_on = 0
        self.plots_off = 0
        self.mode = 0
        """ mode can be set to one five values:
            (0) Menu
            (1) Strength calibration
            (2) Strength trial
            (3) Skill calibration
            (4) Skill trial     """


#===============================================================================
# CLASS: ConfigPanel(wx.Frame)
#    This class implements the view window for the configuration settings.
#===============================================================================
class ConfigPanel(wx.Frame):
    def __init__(self, parent=None, ID=-1, title="Configuration Panel", cfg = ConfigData):
        wx.Frame.__init__(self, parent, ID, title)
        self.parent = parent
        self.panel = wx.Panel(self, -1)
        self.cfg = cfg
        
        # Session options
        self.trials_per_session_text = wx.StaticText(self.panel, -1, 'Trials per session')
        self.trials_per_session = wx.SpinCtrl(self.panel, min=1, max=500, initial=self.cfg._trials_per_session)
        self.trials_per_block_text = wx.StaticText(self.panel, -1, 'Trials per block')
        self.trials_per_block = wx.SpinCtrl(self.panel, min=1, max=500, initial=self.cfg._trials_per_block)
        self.break_len_text = wx.StaticText(self.panel, -1, 'Break length\n(seconds)')
        self.break_len = wx.SpinCtrl(self.panel, min=10, max=600, initial=self.cfg._break_len)
        self.trial_len_text = wx.StaticText(self.panel, -1, 'Trial length\n(seconds)')
        self.trial_len = wx.SpinCtrl(self.panel, min=5, max=60, initial=self.cfg._trial_len)
        
        # Plot options
        self.y_axis_max_text = wx.StaticText(self.panel, -1, 'Y axis max\n(calibration only)')
        self.y_axis_max = wx.SpinCtrl(self.panel, min=50, max=500, initial=self.cfg._y_axis_max_init)
        self.plot_back_color_text = wx.StaticText(self.panel, -1, 'Plot background color')
        self.plot_back_color = wx.ColourPickerCtrl(self.panel, -1, self.__unconvert_color(self.cfg._plot_back_color))
        self.plot_line_color_text = wx.StaticText(self.panel, -1, 'Plot line color')
        self._plot_line_color = wx.ColourPickerCtrl(self.panel, -1, self.__unconvert_color(self.cfg._plot_line_color))
        self.plot_line_width_text = wx.StaticText(self.panel, -1, 'Plot line width')
        self.plot_line_width = wx.SpinCtrl(self.panel, min=1, max=10, initial=self.cfg._plot_line_width)
        self.target_line_width_text = wx.StaticText(self.panel, -1, 'Strength target width')
        self.target_line_width = wx.SpinCtrl(self.panel, min=1, max=10, initial=self.cfg._target_line_width)
        self.target_color_text = wx.StaticText(self.panel, -1, 'Target box color')
        self.target_color = wx.ColourPickerCtrl(self.panel, -1, self.__unconvert_color(self.cfg._target_color))
        
        # Skill options
        self.increment_text = wx.StaticText(self.panel, -1, 'Target increment %')
        self.increment = wx.SpinCtrl(self.panel, min=1, max=99, initial=self.cfg._increment)
        self.hit_tol_text = wx.StaticText(self.panel, -1, 'Hit tolerance')
        self.hit_tol = wx.SpinCtrl(self.panel, min=1, max=100, initial=self.cfg._hit_tol)
        self.miss_tol_text = wx.StaticText(self.panel, -1, 'Miss tolerance')
        self.miss_tol = wx.SpinCtrl(self.panel, min=1, max=100, initial=self.cfg._miss_tol)
        self.running_count_text = wx.StaticText(self.panel, -1, 'Running count')
        self.running_count = wx.CheckBox(self.panel, -1, "")
        self.running_count.SetValue(self.cfg._running_count)
        self.hit_incr_text = wx.StaticText(self.panel, -1, 'Hit increment')
        self.hit_incr = wx.SpinCtrl(self.panel, min=1, max=100, initial=self.cfg._hit_incr)
        self.miss_incr_text = wx.StaticText(self.panel, -1, 'Miss increment')
        self.miss_incr = wx.SpinCtrl(self.panel, min=1, max=100, initial=self.cfg._miss_incr)
        self.target_aspect_ratio_text = wx.StaticText(self.panel, -1, 'Fixed target aspect ratio\n(on=square, off=rectangle)')
        self.target_aspect_ratio = wx.CheckBox(self.panel, -1, "")
        self.target_aspect_ratio.SetValue(self.cfg._target_aspect_ratio)
        self.use_fading_text = wx.StaticText(self.panel, -1, 'Use fading schedule')
        self.use_fading = wx.CheckBox(self.panel, -1, "")
        self.use_fading.SetValue(self.cfg._use_fading)
        self.use_delay_text = wx.StaticText(self.panel, -1, 'Use delayed feedback')
        self.use_delay = wx.CheckBox(self.panel, -1, "")
        self.use_delay.SetValue(self.cfg._use_delay)

        # Strength options
        self.str_increment_text = wx.StaticText(self.panel, -1, 'Target increment %')
        self.str_increment = wx.SpinCtrl(self.panel, min=1, max=99, initial=self.cfg._str_increment)
        self.str_hit_tol_text = wx.StaticText(self.panel, -1, 'Hit tolerance')
        self.str_hit_tol = wx.SpinCtrl(self.panel, min=1, max=100, initial=self.cfg._str_hit_tol)
        self.str_miss_tol_text = wx.StaticText(self.panel, -1, 'Miss tolerance')
        self.str_miss_tol = wx.SpinCtrl(self.panel, min=1, max=100, initial=self.cfg._str_miss_tol)
        self.str_running_count_text = wx.StaticText(self.panel, -1, 'Running count')
        self.str_running_count = wx.CheckBox(self.panel, -1, "")
        self.str_running_count.SetValue(self.cfg._str_running_count)
        self.str_hit_incr_text = wx.StaticText(self.panel, -1, 'Hit increment')
        self.str_hit_incr = wx.SpinCtrl(self.panel, min=1, max=100, initial=self.cfg._str_hit_incr)
        self.str_miss_incr_text = wx.StaticText(self.panel, -1, 'Miss increment')
        self.str_miss_incr = wx.SpinCtrl(self.panel, min=1, max=100, initial=self.cfg._str_miss_incr)
        
        # Misc options
        self.port_text = wx.StaticText(self.panel, -1, 'Serial port')
        port_int = int(self.cfg._port[3:])
        self.port = wx.SpinCtrl(self.panel, min=1, max=20, initial=port_int)
        self.sample_rate_text = wx.StaticText(self.panel, -1, 'Sample rate (Hz)')
        self.sample_rate = wx.ComboBox(self.panel, -1, choices=["10", "20"], style=wx.CB_DROPDOWN|wx.CB_READONLY)
        self.sample_rate.Enable(False)
        
        # Make a button to save options
        self.save_button = wx.Button(self.panel, -1, 'Save and Exit', size=(100, 30))
        self.Bind(wx.EVT_BUTTON, self.__on_save_exit, self.save_button)
        self.Bind(wx.EVT_CLOSE, self.__on_close)

        self.__do_layout()
        
    def __do_layout(self):
        # Add controls to a grid sizer
        sess_szr = wx.GridSizer(4, 2)
        sess_szr.Add(self.trials_per_session_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        sess_szr.Add(self.trials_per_session, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        sess_szr.Add(self.trials_per_block_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        sess_szr.Add(self.trials_per_block, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        sess_szr.Add(self.break_len_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        sess_szr.Add(self.break_len, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        sess_szr.Add(self.trial_len_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        sess_szr.Add(self.trial_len, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        
        plot_szr = wx.FlexGridSizer(5, 2)
        plot_szr.Add(self.y_axis_max_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        plot_szr.Add(self.y_axis_max, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        plot_szr.Add(self.plot_back_color_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        plot_szr.Add(self.plot_back_color, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        plot_szr.Add(self.plot_line_color_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        plot_szr.Add(self._plot_line_color, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        plot_szr.Add(self.plot_line_width_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        plot_szr.Add(self.plot_line_width, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        plot_szr.Add(self.target_line_width_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        plot_szr.Add(self.target_line_width, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        plot_szr.Add(self.target_color_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        plot_szr.Add(self.target_color, 0, wx.ALL | wx.ALIGN_CENTER, 2)

        skill_szr = wx.GridSizer(7, 2)
        skill_szr.Add(self.increment_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        skill_szr.Add(self.increment, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        skill_szr.Add(self.hit_tol_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        skill_szr.Add(self.hit_tol, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        skill_szr.Add(self.miss_tol_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        skill_szr.Add(self.miss_tol, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        skill_szr.Add(self.running_count_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        skill_szr.Add(self.running_count, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        skill_szr.Add(self.hit_incr_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        skill_szr.Add(self.hit_incr, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        skill_szr.Add(self.miss_incr_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        skill_szr.Add(self.miss_incr, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        
        cb_gridsizer = wx.FlexGridSizer(3,2)
        cb_gridsizer.Add(self.target_aspect_ratio_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        cb_gridsizer.Add(self.target_aspect_ratio, 1, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 2)
        cb_gridsizer.Add(self.use_fading_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        cb_gridsizer.Add(self.use_fading, 1, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 2)
        cb_gridsizer.Add(self.use_delay_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        cb_gridsizer.Add(self.use_delay, 1, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 2)

        str_szr = wx.GridSizer(6, 2)
        str_szr.Add(self.str_increment_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        str_szr.Add(self.str_increment, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        str_szr.Add(self.str_hit_tol_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        str_szr.Add(self.str_hit_tol, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        str_szr.Add(self.str_miss_tol_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        str_szr.Add(self.str_miss_tol, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        str_szr.Add(self.str_running_count_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        str_szr.Add(self.str_running_count, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        str_szr.Add(self.str_hit_incr_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        str_szr.Add(self.str_hit_incr, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        str_szr.Add(self.str_miss_incr_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        str_szr.Add(self.str_miss_incr, 0, wx.ALL | wx.ALIGN_CENTER, 2)

        misc_szr = wx.GridSizer(2, 2)
        misc_szr.Add(self.port_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        misc_szr.Add(self.port, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        misc_szr.Add(self.sample_rate_text, 0, wx.ALL | wx.ALIGN_CENTER, 2)
        misc_szr.Add(self.sample_rate, 0, wx.ALL | wx.ALIGN_CENTER, 2)

        # Place gridsizers inside boxes
        box1 = wx.StaticBox(self.panel, -1, 'Session options')
        boxsizer1 = wx.StaticBoxSizer(box1, wx.VERTICAL)
        boxsizer1.Add(sess_szr)
        
        box2 = wx.StaticBox(self.panel, -1, 'Plot options')
        boxsizer2 = wx.StaticBoxSizer(box2, wx.VERTICAL)
        boxsizer2.Add(plot_szr)
        
        box3 = wx.StaticBox(self.panel, -1, 'Skill training options')
        boxsizer3 = wx.StaticBoxSizer(box3, wx.VERTICAL)
        boxsizer3.Add(skill_szr, 1)
        boxsizer3.Add(cb_gridsizer, 0, wx.ALL, 5)
        
        box4 = wx.StaticBox(self.panel, -1, 'Miscellaneous options')
        boxsizer4 = wx.StaticBoxSizer(box4, wx.VERTICAL)
        boxsizer4.Add(misc_szr, 0, wx.EXPAND)
        
        box5 = wx.StaticBox(self.panel, -1, 'Strength training options')
        boxsizer5 = wx.StaticBoxSizer(box5, wx.VERTICAL)
        boxsizer5.Add(str_szr, 0, wx.EXPAND)
        
        left_sizer = wx.BoxSizer(wx.VERTICAL)
        left_sizer.Add(boxsizer1, 0, wx.ALL, 5)
        left_sizer.Add(boxsizer2, 0, wx.ALL, 5)
        left_sizer.Add(boxsizer4, 0, wx.ALL, 5)
        right_sizer = wx.BoxSizer(wx.VERTICAL)
        right_sizer.Add(boxsizer5, 0, wx.ALL, 5)
        right_sizer.Add(boxsizer3, 0, wx.ALL, 5)
        options = wx.BoxSizer(wx.HORIZONTAL)
        options.Add(left_sizer)
        options.Add(right_sizer)
        
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(options, 0, wx.ALL | wx.ALIGN_CENTER, 10)
        sizer.Add(self.save_button, 0, wx.ALL | wx.ALIGN_CENTER, 10)

        self.panel.SetSizer(sizer)
        sizer.Fit(self)

    def __save_config(self):
        # Save options to file
        self.cfg._trials_per_session = self.trials_per_session.GetValue()
        self.cfg._trials_per_block = self.trials_per_block.GetValue()
        self.cfg._trial_len = self.trial_len.GetValue()
        self.cfg._break_len = self.break_len.GetValue()
        self.cfg._y_axis_max = self.y_axis_max.GetValue()

        self.cfg._plot_back_color = self.__convert_color(self.plot_back_color.GetColour())
        self.cfg._plot_line_color = self.__convert_color(self._plot_line_color.GetColour())
        self.cfg._plot_line_width = self.plot_line_width.GetValue()
        self.cfg._target_line_width = self.target_line_width.GetValue()
        self.cfg._target_color = self.__convert_color(self.target_color.GetColour())

        self.cfg._str_increment = self.str_increment.GetValue()
        self.cfg._str_hit_tol = self.str_hit_tol.GetValue()
        self.cfg._str_miss_tol = self.str_miss_tol.GetValue()
        self.cfg._str_running_count = self.str_running_count.GetValue()
        self.cfg._str_hit_incr = self.str_hit_incr.GetValue()
        self.cfg._str_miss_incr = self.str_miss_incr.GetValue()
        
        self.cfg._increment = self.increment.GetValue()
        self.cfg._hit_tol = self.hit_tol.GetValue()
        self.cfg._miss_tol = self.miss_tol.GetValue()
        self.cfg._running_count = self.running_count.GetValue()
        self.cfg._hit_incr = self.hit_incr.GetValue()
        self.cfg._miss_incr = self.miss_incr.GetValue()
        self.cfg._target_aspect_ratio = self.target_aspect_ratio.GetValue()
        self.cfg._use_fading = self.use_fading.GetValue()
        self.cfg._use_delay = self.use_delay.GetValue()
        
        self.cfg._port = 'COM' + str(self.port.GetValue())
#        self.cfg._sample_rate = int(self.sample_rate.GetValue())
        
        sys.stdout.write("Configuration saved.\n")
        if self.parent:
            self.parent.app.status.patient_changed = True
        
    def __convert_color(self, old):
        tup = old.Get(True)
        new = (tup[0]/255.0, tup[1]/255.0, tup[2]/255.0, tup[3]/255.0)
        return new
    
    def __unconvert_color(self, old):
        new = (int(old[0]*255), int(old[1]*255), int(old[2]*255), int(old[3]*255))
        return new
        
    def __on_save_exit(self, event):
        self.__save_config()
        self.__exit()
        
    def __on_close(self, event):
        dialog_text = "Save settings?"
        dial = wx.MessageDialog(None, dialog_text, 'Question',
                                wx.YES_NO | wx.ICON_QUESTION)
        ret = dial.ShowModal()
        if ret == wx.ID_YES:
            self.__save_config()
        self.__exit()
        
    def __exit(self):
        self.MakeModal(False)
        self.Destroy()
        if self.parent:
            self.parent.SetFocus()
        
    def cfg_update(self):
        # Update control values from file, except for colour values
        self.trials_per_session.SetValue(self.cfg._trials_per_session) 
        self.trials_per_block.SetValue(self.cfg._trials_per_block)
        self.trial_len.SetValue(self.cfg._trial_len)
        self.break_len.SetValue(self.cfg._break_len)
        self.y_axis_max.SetValue(self.cfg._y_axis_max)
        self.plot_line_width.SetValue(self.cfg._plot_line_width)
        self.str_increment.SetValue(self.cfg._str_increment)
        self.str_hit_tol.SetValue(self.cfg._str_hit_tol)
        self.str_miss_tol.SetValue(self.cfg._str_miss_tol)
        self.str_hit_incr.SetValue(self.cfg._str_hit_incr)
        self.str_miss_incr.SetValue(self.cfg._str_miss_incr)
        self.str_running_count.SetValue(self.cfg._str_running_count)
        self.increment.SetValue(self.cfg._increment)
        self.hit_tol.SetValue(self.cfg._hit_tol)
        self.miss_tol.SetValue(self.cfg._miss_tol)
        self.hit_incr.SetValue(self.cfg._hit_incr)
        self.miss_incr.SetValue(self.cfg._miss_incr)
        self.running_count.SetValue(self.cfg._running_count)
        self.target_aspect_ratio.SetValue(self.cfg._target_aspect_ratio)
        self.use_fading.SetValue(self.cfg._use_fading)
        self.use_delay.SetValue(self.cfg._use_delay)
        self.port.SetValue(int(self.cfg._port[3:]))

# End of config.py